//
//  ReminderDataSource.m
//  Pocket Doctor alpha version
//
//  Created by Sherif, Yin, Taylor, Jacob, Anna, Mike on 11-11-22.
//  Copyright (c) 2011 __Sytjam__. All rights reserved.
//
//Class Description: Stores reminder information to feed into the calendar.
//
//Known Bugs: none.
//
//Incomplete Feature: Loading medicine view when choosing a medicine in the table view.
//                    This feature couldnt be implemented because the UITableViewDelegate wouldn't
//                    work simply by putting in the function; rather more complex editing has to take place
//

#import "ReminderDataSource.h"
#import "CalReminder.h"

#import "AppDelegate.h"

static BOOL IsDateBetweenInclusive(NSDate *date, NSDate *begin, NSDate *end)
{
    return [date compare:begin] != NSOrderedAscending && [date compare:end] != NSOrderedDescending;
}
@interface ReminderDataSource()
- (NSArray *)remindersFrom:(NSDate *)fromDate to:(NSDate *)toDate;
@end

int clockSetting;
int dateSetting;
int daySetting;

@implementation ReminderDataSource

@synthesize aD;

+ (ReminderDataSource *)dataSource
{
    return [[[[self class] alloc] init] autorelease];
}

- (id)init
{
    if ((self = [super init])) {
        items = [[NSMutableArray alloc] init];
        reminders = [[NSMutableArray alloc] init];
        
         aD = [[UIApplication sharedApplication] delegate];
        
        sqlite3_stmt *statement;
        const char * query_stmt;
        NSString *loadSettings= @"SELECT clock_setting, date_setting, day_setting FROM Settings;";
        query_stmt = [loadSettings UTF8String];
        
        if (sqlite3_prepare_v2(aD.dbPointer, query_stmt, -1, &statement, NULL) == SQLITE_OK){
            
            if (sqlite3_step(statement) == SQLITE_ROW){
                clockSetting = sqlite3_column_int(statement, 0);
                dateSetting = sqlite3_column_int(statement, 1);
                daySetting = sqlite3_column_int(statement, 2);
                
            }
        }
        
        [loadSettings release];
    }
    return self;
    
}

- (CalReminder *)reminderAtIndexPath:(NSIndexPath *)indexPath
{
    return [items objectAtIndex:indexPath.row];
    
}

#pragma mark UITableViewDataSource protocol conformance

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *identifier = @"MyCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if(!cell){
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
        
        // others
    }
    
    CalReminder *reminder = [self reminderAtIndexPath:indexPath];
    
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    if (daySetting==0 && clockSetting==0) {
        [dateFormatter setDateFormat:@"EEEE, h:mm a"];
    }else
        if (daySetting==0 && clockSetting ==1) {
            [dateFormatter setDateFormat:@"EEEE, H:mm"];
        }else
            if (daySetting==1 && clockSetting==0) {
                [dateFormatter setDateFormat:@"EEE, h:mm a"];
            }else{
                [dateFormatter setDateFormat:@"EEE, H:mm"];
            }
    
    
    NSDateFormatter *yearFormatter = [[NSDateFormatter alloc]init];
    if (dateSetting==0) {
        [yearFormatter setDateFormat:@"MMM/dd/yyy"];
    }else{
        [yearFormatter setDateFormat:@"dd/MMM/yyy"];
    }
    
    NSString *reminderDate = [[NSString alloc]initWithFormat:@"%@ starting on %@",[dateFormatter stringFromDate:reminder.date], [yearFormatter stringFromDate:reminder.date]]; //change according our liking.
    
    
    cell.textLabel.text = reminder.name;
    cell.detailTextLabel.text = reminderDate;
    
    [dateFormatter release];
    [yearFormatter release];
    
    return cell;
    
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [items count];

}
#pragma mark reminder loading

- (void)loadRemindersFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate
{
    NSArray * notiflist = [[UIApplication sharedApplication] scheduledLocalNotifications];
    NSEnumerator *e = [notiflist objectEnumerator];
    UILocalNotification * notification;
    while (notification = [e nextObject]) {
        NSDate *date = notification.fireDate;
        NSString *name = [notification.userInfo objectForKey:@"medName"];
        [reminders addObject:[CalReminder reminderNamed:name date:date]];
    }
    
//    [reminders addObject:[CalReminder //stuff
    [delegate loadedDataSource:self];
    
}

#pragma mark KalDataSource protocol conformance

//Called when the month is switched, presenting the dates from the beginning of the new month to the end of the new month.
- (void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate
{
    //flush and reload
    [reminders removeAllObjects];
    [self loadRemindersFrom:fromDate to:toDate delegate:delegate];
}

//Called when the underlying list of reminder changes in content. (Switching a month)
- (NSArray *)markedDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate
{
    return [[self remindersFrom:fromDate to:toDate] valueForKeyPath:@"date"];
}

//Loads the reminder objects for each medicine into the local array buffer.
//Called when the calendar table cell selection is changed.
- (void)loadItemsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
    [items addObjectsFromArray:[self remindersOfTheDay:fromDate to:toDate]];
}

//Called when the calendar view is changed, such as switching a month.
- (void)removeAllItems
{
    [items removeAllObjects];
}

//Called when the query for the date range for reminder objects change.
- (NSArray *)remindersFrom:(NSDate *)fromDate to:(NSDate *)toDate
{
    NSMutableArray *matches = [NSMutableArray array];
    NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents * offsetByDay = [[NSDateComponents alloc] init];
    [offsetByDay setDay:1];
    NSDate * nextDay = fromDate;
    while ([nextDay compare: toDate] == NSOrderedAscending) 
    {
        for (CalReminder *reminder in reminders)
        {
            NSInteger weekdayIndex = [self getWeekday:nextDay];
            NSInteger reminderWeekdayIndex = [self getWeekday:reminder.date];
            if(weekdayIndex == reminderWeekdayIndex && [reminder.date compare:toDate] == NSOrderedAscending )
            {
                if ([reminder.date compare: nextDay] == NSOrderedSame || [reminder.date compare: nextDay] == NSOrderedAscending) {
                    CalReminder * markedDate = [[CalReminder alloc] initWithName:@"" date: nextDay];
                    [matches addObject:markedDate];
                    break;
                }
            }
        }
        nextDay = [gregorian dateByAddingComponents:offsetByDay toDate:nextDay options:0];
    }
    [offsetByDay release];
    [gregorian release];
    
    for (CalReminder *reminder in reminders)
    {
        [matches addObject:reminder];
    }
    return matches;
}

- (NSArray *)remindersOfTheDay:(NSDate *)fromDate to:(NSDate *)toDate
{
	NSMutableArray *matches = [NSMutableArray array];
	NSInteger weekdayIndex = [self getWeekday:fromDate];
	
	//For each reminder in the data source, check if the weekday of the reminder's creation date and the current day are the same, AND whether the current day is later than the creation day. Both are true -> add into array.
	for (CalReminder *reminder in reminders)
	{
		NSInteger reminderWeekday = [self getWeekday: reminder.date];
        NSComparisonResult dateCompResult = [reminder.date compare:toDate];
		if (reminderWeekday == weekdayIndex && dateCompResult == NSOrderedAscending) 
		{
			[matches addObject:reminder];
		}
	}
	return matches;
}

- (NSInteger) getWeekday: (NSDate *) dateOfInterest
{
    NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; //Make a gregorian calendar
	NSDateComponents *weekdayComponents =[gregorian components:NSWeekdayCalendarUnit fromDate:dateOfInterest]; //Extract the calculated date component data structure
	NSInteger weekday = [weekdayComponents weekday]; //Retrieve the weekday index.
	[gregorian release];
	return weekday;
}

- (void)dealloc
{
    [aD release];
    
    [items release];
    [reminders release];
    [super dealloc];
}
@end
